package com.example.twoscroolview.view

import android.animation.ValueAnimator
import android.graphics.*
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.animation.LinearInterpolator
import kotlin.math.sin


/**
 * 绘制鱼+鱼的动画
 */
class FishDrawable : Drawable() {
    //鱼头圆心的点的坐标
    lateinit var headPoint: PointF
    var mPaint: Paint? = null
    var mPath: Path? = null
    val OTHER_ALPHA = 110
    val NOMAL_FREQUENCE = 2f //正常频率
    //鱼开始游戏加速度
    var frequence = 2f

    /**
     * //鱼的重心坐标（中心 鱼游动转圈会根据这个值）
     */
    var mMiddlePoint: PointF? = null

    //鱼头摇晃的主要角度 0 为右 90 为上
    var mFishMainAngle = 90f

    //鱼头的大小 高度
    val HEAD_RADIUS = 40f

    //身体的成都
    val BODY_LENGTH = HEAD_RADIUS * 3.2F

    //寻找鱼鳍起点坐标
    //鱼鳍的长度
    val FIND_FINS_LENTH = 0.9F * HEAD_RADIUS
    val FINS_LENTH = 1.3F * HEAD_RADIUS

    //鱼尾
    // 鱼尾巴上圆下圆组成一个梯形 半径
    private val BIG_CIRCLE_RADIUS: Float = (0.7 * HEAD_RADIUS).toFloat()//尾巴第一个大圆的半径
    private val MIDDLE_CIRCLE_RADIUS: Float = (0.6 * BIG_CIRCLE_RADIUS).toFloat()//尾巴中心圆的半径
    private val SMALL_CIRCLE_RADIUS: Float = (0.4 * MIDDLE_CIRCLE_RADIUS).toFloat()//尾巴最小圆的半径

    //线长
    private val FIND_MIDDLE_CIRCLE_LENGTH: Float = ((0.6 + 1f) * BIG_CIRCLE_RADIUS).toFloat()
    private val FIND_SMALL_CIRCLE_LENGTH: Float = ((0.4 + 2.7) * MIDDLE_CIRCLE_RADIUS).toFloat()

    //三角形的线长
    private val FIND_TRIANGLE: Float = (MIDDLE_CIRCLE_RADIUS * 2.7).toFloat()
    private var animatorValue = 0f

    //眼镜半径
    private val EYE_CIRCLE = HEAD_RADIUS * 0.1f
    init {
        mPaint = Paint()
        mPath = Path()
        mPaint?.isAntiAlias = true
        mPaint?.isDither = true
        mPaint?.style = Paint.Style.FILL
        mPaint?.setARGB(OTHER_ALPHA, 244, 92, 71)
        //先定下鱼的重心的坐标
        //头圆半径的4.19倍，这个其实是自己定的，5f,6f都行，就是只改变鱼的长度，用鱼头半径做初始单位有利于改变整个鱼的大小。
        mMiddlePoint = PointF(4.19f * HEAD_RADIUS, 4.19f * HEAD_RADIUS)
        val valueAnimator = ValueAnimator.ofFloat(0f, 720f)
        valueAnimator.duration = 15 * 1000
        valueAnimator.repeatMode = ValueAnimator.RESTART
        valueAnimator.repeatCount = ValueAnimator.INFINITE
        valueAnimator.interpolator = LinearInterpolator()
        valueAnimator.addUpdateListener {
            animatorValue = it.animatedValue as Float
            invalidateSelf()
        }

        valueAnimator.start()
    }

    override fun draw(canvas: Canvas) {
        //鱼头朝向 默认0   ，toRadians=将以度为单位测量的角度转换为以弧度测量的近似等效角度。从度数到弧度的转换通常是不精确的。
        val fishAngle: Float =
            (mFishMainAngle + sin(Math.toRadians(animatorValue.toDouble() * 1.2)) * 10).toFloat()
        headPoint = calculatePoint(mMiddlePoint!!, BODY_LENGTH / 2, fishAngle)//鱼头圆心的点
        canvas.drawCircle(headPoint.x, headPoint.y, HEAD_RADIUS, mPaint!!)
        makeFins(canvas, fishAngle, true)//绘制右鱼鳍
        makeFins(canvas, fishAngle, false)//绘制左鱼鳍
        val bodyBottomCenterPoint = calculatePoint(headPoint, BODY_LENGTH, fishAngle - 180)//得到第一个梯形长边中心点
        //绘制上节支，得到第二个梯形长边中心点PointF，也就是三角形的顶点
        val PointF = makeSegment(
            canvas,
            bodyBottomCenterPoint,
            BIG_CIRCLE_RADIUS,
            MIDDLE_CIRCLE_RADIUS,
            FIND_MIDDLE_CIRCLE_LENGTH,
            fishAngle,
            true
        )
        //绘制下节支
        makeSegment(
            canvas,
            PointF,
            MIDDLE_CIRCLE_RADIUS,
            SMALL_CIRCLE_RADIUS,
            FIND_SMALL_CIRCLE_LENGTH,
            fishAngle,
            false
        )
        //绘制尾巴
//        val triangleLength = Math.abs((Math.sin(Math.toRadians(animatorValue.toDouble()))*1.5).toFloat()*BIG_CIRCLE_RADIUS)
//        maketriangel(canvas, PointF!!,fishAngle,triangleLength,BIG_CIRCLE_RADIUS)
//        maketriangel(canvas, PointF!!,fishAngle,triangleLength-20,BIG_CIRCLE_RADIUS-20)
        maketriangel(canvas, PointF!!, fishAngle, FIND_TRIANGLE, BIG_CIRCLE_RADIUS)   //绘制大三角形，
        maketriangel(canvas, PointF!!, fishAngle, FIND_TRIANGLE - 10, BIG_CIRCLE_RADIUS - 20)   //绘制小三角形
        //绘制身体
        makeBody(canvas, headPoint!!, bodyBottomCenterPoint, fishAngle)

        //画眼睛
        makeEyes(canvas, headPoint, fishAngle)
    }

    private fun makeEyes(canvas: Canvas, headPoint: PointF, fishAngle: Float) {
        val leftEye = calculatePoint(headPoint, HEAD_RADIUS, fishAngle + 45)
        val rightEye = calculatePoint(headPoint, HEAD_RADIUS, fishAngle - 45)
        canvas.drawCircle(leftEye.x, leftEye.y, EYE_CIRCLE, mPaint!!)
        canvas.drawCircle(rightEye.x, rightEye.y, EYE_CIRCLE, mPaint!!)
    }
    /**
     * 绘制身体
     */
    private fun makeBody(
        canvas: Canvas,
        headPoint: PointF,
        bigCircleCenterPoint: PointF,
        fishAngle: Float
    ) {
        // 先求头部圆和大圆直径上的四个点
        val upperLeftPoint = calculatePoint(headPoint, HEAD_RADIUS, fishAngle + 90)
        val upperRightPoint = calculatePoint(headPoint, HEAD_RADIUS, fishAngle - 90)
        val bottomLeftPoint =
            calculatePoint(bigCircleCenterPoint, BIG_CIRCLE_RADIUS, fishAngle + 90)
        val bottomRightPoint =
            calculatePoint(bigCircleCenterPoint, BIG_CIRCLE_RADIUS, fishAngle - 90)

        // 两侧的控制点，长度和角度是在画图调整后测量出来的
        val controlLeft = calculatePoint(headPoint, BODY_LENGTH * 0.56f, fishAngle + 130)
        val controlRight = calculatePoint(headPoint, BODY_LENGTH * 0.56f, fishAngle - 130)

        // 绘制
        mPath!!.reset()
        mPath!!.moveTo(upperLeftPoint.x, upperLeftPoint.y)
        mPath!!.quadTo(controlLeft.x, controlLeft.y, bottomLeftPoint.x, bottomLeftPoint.y)
        mPath!!.lineTo(bottomRightPoint.x, bottomRightPoint.y)
        mPath!!.quadTo(controlRight.x, controlRight.y, upperRightPoint.x, upperRightPoint.y)
        mPaint!!.alpha = OTHER_ALPHA
        canvas.drawPath(mPath!!, mPaint!!)
    }


    /**
     *  startPoint ：三角形的顶点
     *fishAngle：鱼头朝向
     * find_triangle：三角形的高
     * big_circle_radius：三角形底部边长的一半
     */
    private fun maketriangel(
        canvas: Canvas,
        startPoint: PointF,
        fishAngle: Float,
        find_triangle: Float,
        big_circle_radius: Float
    ) {
        //下节支比上节支慢一个节拍，用 Math.cos, 头部频率10，节支频率为15，尾巴频率为35，
        val triAngle =
            (fishAngle + Math.cos(Math.toRadians(animatorValue.toDouble() * frequence)) * 35).toFloat()
        val centerPoint = calculatePoint(startPoint, find_triangle, triAngle - 180)//三角形底部的中心点

        val leftPoint = calculatePoint(centerPoint, big_circle_radius, triAngle + 90)//三角形左下角
        val rightPoint = calculatePoint(centerPoint, big_circle_radius, triAngle - 90)//三角形右下角

        //绘制三角形
        mPath?.reset()
        mPath?.moveTo(startPoint.x, startPoint.y)
        mPath?.lineTo(leftPoint.x, leftPoint.y)
        mPath?.lineTo(rightPoint.x, rightPoint.y)
        canvas.drawPath(mPath!!, mPaint!!)
    }

    /**
     * 画锦鲤节支
     *bottomCenterPoint：梯形长边圆的圆心
     * big_radius：梯形长边半径
     * small_radius：梯形短边半径
     * fishAngle：鱼头朝向
     * hasBig：梯形长边有没有圆
     */
    private fun makeSegment(
        canvas: Canvas,
        bottomCenterPoint: PointF,
        big_radius: Float,
        small_radius: Float,
        find_middle_circle_length: Float,
        fishAngle: Float,
        hasBig: Boolean
    ): PointF {
        var segmentAngle: Float = 0f //朝向，方向角
        if (hasBig) {
            segmentAngle =
                (fishAngle + Math.cos(Math.toRadians(animatorValue.toDouble() * frequence)) * 15).toFloat()
        } else {
            segmentAngle =
                (fishAngle + Math.cos(Math.toRadians(animatorValue.toDouble() * frequence)) * 35).toFloat()
        }

        //梯形短边圆的圆心
        val upCenterPoint =
            calculatePoint(bottomCenterPoint, find_middle_circle_length, segmentAngle - 180)
        //梯形的四个点
        val bottomLeft = calculatePoint(bottomCenterPoint, big_radius, segmentAngle + 90)//长边左
        val bottomRight = calculatePoint(bottomCenterPoint, big_radius, segmentAngle - 90)
        val upLeft = calculatePoint(upCenterPoint, small_radius, segmentAngle + 90)//短边左
        val upRight = calculatePoint(upCenterPoint, small_radius, segmentAngle - 90)
        //画大圆（如果梯形长边有圆）
        if (hasBig) {
            canvas.drawCircle(bottomCenterPoint.x, bottomCenterPoint.y, big_radius, mPaint!!)
        }
        //画小圆（梯形短边）
        canvas.drawCircle(upCenterPoint.x, upCenterPoint.y, small_radius, mPaint!!)
        //绘制梯形
        mPath?.reset()
        mPath?.moveTo(upLeft.x, upLeft.y)
        mPath?.lineTo(upRight.x, upRight.y)
        mPath?.lineTo(bottomRight.x, bottomRight.y)
        mPath?.lineTo(bottomLeft.x, bottomLeft.y)
        canvas?.drawPath(mPath!!, mPaint!!)
        return upCenterPoint// 返回梯形短边圆的圆心
    }

    /**
     * 绘制鱼鳍
     * startPoint：鱼鳍的起点
     * fishAngle：鱼头的朝向
     * isRight：是否为右鱼鳍
     */
    private fun makeFins(canvas: Canvas, fishAngle: Float, isRight: Boolean) {
        Log.e("mytag", "makeFins======")
        //鱼鳍的起点
        val startPoint = if (isRight) {
            calculatePoint(headPoint, FIND_FINS_LENTH, fishAngle - 110) //右鱼鳍的起点
        } else {
            calculatePoint(headPoint, FIND_FINS_LENTH, fishAngle + 110)//左鱼鳍的起点
        }
        val controlAngle = 115  //控制点角度
        //鱼鳍的终点 ，也是鱼鳍贝塞尔曲线的重点
        val endPoint = calculatePoint(startPoint, FINS_LENTH, fishAngle - 180)
        //贝塞尔曲线的控制点
        val controlPoint = if (isRight) {
            calculatePoint(startPoint, FINS_LENTH * 1.8f, fishAngle - controlAngle)//右鱼鳍的贝塞尔曲线的控制点
        } else {
            calculatePoint(startPoint, FINS_LENTH * 1.8f, fishAngle + controlAngle)//左鱼鳍的贝塞尔曲线的控制点
        }
        Log.e("mytag", "startPoint======${startPoint.x}---${startPoint.y}")
        mPath?.reset()
        //  移动到起始点
        mPath?.moveTo(startPoint.x, startPoint.y)
        // 2阶贝塞尔曲线
        Log.e("mytag", "controlPoint======${controlPoint.x}---${controlPoint.y}")
        Log.e("mytag", "endPoint======${endPoint.x}---${endPoint.y}")
        mPath?.quadTo(controlPoint.x, controlPoint.y, endPoint.x, endPoint.y)
        canvas.drawPath(mPath!!, mPaint!!)
    }

    /**
     * @param startPointF起始点
     * @param length 鱼头摇晃旋转线的长度
     * @param angle 鱼头摇晃的角度
     *
     */
    fun calculatePoint(startPointF: PointF, length: Float, angle: Float): PointF {

        //toRadians角度转弧度
        //鱼头相对远点的x y坐标
        val deltaX: Float = (Math.cos(Math.toRadians(angle.toDouble())) * length).toFloat()
        val deltaY: Float =
            (Math.sin(Math.toRadians(angle.minus(180).toDouble())) * length).toFloat()
        return PointF(startPointF.x + deltaX, startPointF.y + deltaY)
    }

    //赋值给paint
    override fun setAlpha(alpha: Int) {
        mPaint?.alpha = alpha
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        mPaint?.colorFilter = colorFilter
    }

    /**
     * 根据透明值调整
     */
    override fun getOpacity(): Int {
        return PixelFormat.TRANSLUCENT
    }

    override fun getIntrinsicHeight(): Int {
        return (9.38 * HEAD_RADIUS).toInt()
    }

    override fun getIntrinsicWidth(): Int {
        return (9.38 * HEAD_RADIUS).toInt()
    }
}